home *** CD-ROM | disk | FTP | other *** search
/ Macwelt 1 / Macwelt DVD 1.toast / Web-Publishing / HTML-Editoren / Alpha ƒ / Tcl / SystemCode / appleEvents.tcl < prev    next >
Encoding:
Text File  |  2000-12-15  |  10.6 KB  |  389 lines

  1. # JEG - modernized
  2. # make alias list to pass to AEBuild
  3. proc makeAlis {name} {
  4.     return [tclAE::build::alis $name]
  5. }
  6.  
  7. # JEG - This is unused???
  8. proc makeFile {name} {
  9.     return [tclAE::build::alis $name]    
  10. }
  11.  
  12. ## 
  13.  # -------------------------------------------------------------------------
  14.  # 
  15.  # "makeAlises" --
  16.  # 
  17.  #  This proc has changed so it takes a list of items rather than an
  18.  #  unknown number of args 'args'.  If 'l' is a list you must call
  19.  #  this proc with 'makeAlises $l' rather than 'eval makeAlises $l'
  20.  #  as was previously required.
  21.  # -------------------------------------------------------------------------
  22.  ##
  23.  
  24. # JEG - modernized
  25. proc makeAlises {names} {
  26.     return [tclAE::build::List $names -untyped -as alis]
  27. }
  28.  
  29. ## 
  30.  # -------------------------------------------------------------------------
  31.  # 
  32.  # "handleReply" --
  33.  # 
  34.  #  Queued replies are passed through AEPrint and then to this routine.
  35.  #  
  36.  #  If you write your own handleReply procedure, register it to this
  37.  #  proc with:
  38.  #  
  39.  #    currentReplyHandler 'my-proc-name'
  40.  #    
  41.  #  Do this each time you send an event which may receive a reply.
  42.  #  There is no need to register your proc at startup or any such
  43.  #  'pre-registering'.  Just call the above proc _each_ time.
  44.  #  
  45.  #  You proc should take one parameter (the reply), and should
  46.  #  return '1' if it handled the reply, otherwise it can do/return
  47.  #  anything else (although hopefully not much if it didn't handle
  48.  #  anything).
  49.  #  
  50.  #  If your replies often time-out or have other problems such
  51.  #  that you don't handle them correctly, you may wish to register
  52.  #  your reply-handler with 'currentReplyHandler 'my-proc' 1' which
  53.  #  says 'only register if it's not already registered'.  Or you
  54.  #  may wish to remove duplicates from the list of handlers 
  55.  #  directly.
  56.  #    
  57.  # Results:
  58.  #  depends on what is registered
  59.  # 
  60.  # Side effects:
  61.  #  calls other procs.  Removes handler from queue if it handled
  62.  #  the reply.
  63.  # 
  64.  # --Version--Author------------------Changes-------------------------------
  65.  #    1.0     <vince@santafe.edu> first one with hook handling
  66.  #    2.0     <vince@santafe.edu> different mechanism to give priority
  67.  # -------------------------------------------------------------------------
  68.  ##
  69. proc handleReply {rep} {
  70.     global lastReply replyHandlers
  71.     set lastReply $rep
  72.     set i 0
  73.     foreach h $replyHandlers {
  74.     if {$h != ""} {
  75.         set cmd [concat $h [list $rep]]
  76.         catch $cmd res
  77.         if {$res == 1} {
  78.         set replyHandlers [lreplace $replyHandlers $i $i]
  79.         return
  80.         }
  81.     }
  82.     incr i
  83.     }
  84.     message "Reply '$rep' not handled"
  85. }
  86.  
  87. ensureset replyHandlers ""
  88.  
  89. ## 
  90.  # -------------------------------------------------------------------------
  91.  # 
  92.  # "currentReplyHandler" --
  93.  # 
  94.  #  Add item to end of queue to receive replies, even if it is already
  95.  #  in the queue, unless we set 'nodups'
  96.  # -------------------------------------------------------------------------
  97.  ##
  98. proc currentReplyHandler {proc {nodups 0}} {
  99.     global replyHandlers
  100.     if {!$nodups || (![lcontains replyHandlers $proc])} {
  101.     lappend replyHandlers $proc
  102.     }    
  103. }
  104.  
  105. # JEG - only used by thinkMenu.tcl. Why is it here?
  106. # Return an object record specifying the desired think project file.
  107. proc fileObject {name} {
  108.     join [concat {obj\{want:type('SFIL'), from:'null'(), form:'name', seld:“} [file tail $name] {”\}}] ""
  109. }
  110.  
  111. #• sendOpenEvent [filler] <app name> <file name> - Send an open doc event to 
  112. #  another currently running application. If 'filler' is noReply, then a 
  113. #  reply is not requested. Otherwise, we wait for a reply and 'filler' is 
  114. #  ignored. 
  115. proc sendOpenEvent {filler app filename} {
  116.     global browserSig tcl_platform
  117.     set filename [file nativename $filename]
  118.     switch -- $tcl_platform(platform) {
  119.     "windows" {
  120.         set app [string trim $app ']
  121.         if {[file nativename $app] == [file nativename $browserSig]} {
  122.         global env
  123.         # This command doesn't seem to work with long names/spaces etc
  124.         # on windows, so we convert to the shortname!
  125.         set filename [file attributes $filename -shortname]
  126.         exec $env(COMSPEC) /c start $filename &
  127.         return
  128.         } elseif {$app == "Finder"} {
  129.         if {[file isdirectory $filename]} {
  130.             windows::Show $filename
  131.         } else {
  132.             windows::Launch $filename
  133.         }
  134.         } else {
  135.         if {$filler == "noReply"} {
  136.             exec $app $filename &
  137.         } else {
  138.             return [exec $app $filename]
  139.         }
  140.         }
  141.     }
  142.     "macintosh" {
  143.         global file::separator
  144.         
  145.         # Tcl 8's [file nativename] strips the trailing ':'
  146.         # from directories which screws up the 'alis'
  147.         if {[file type $filename] == "directory" \
  148.           && ![regexp "${file::separator}\$" $filename]} {
  149.         append filename ${file::separator}
  150.         }
  151.         if {$filler == "noReply"} {
  152.         AEBuild $app aevt odoc "----" [makeAlis $filename]
  153.         } else {
  154.         AEBuild -r $app aevt odoc "----" [makeAlis $filename]
  155.         }
  156.     }
  157.     "unix" {
  158.         set app [string trim $app ']
  159.         if {$filler == "noReply"} {
  160.         exec $app $filename &
  161.         } else {
  162.         return [exec $app $filename]
  163.         }
  164.     }
  165.     }
  166.     
  167. }
  168.  
  169. proc launchDoc {name} {
  170.     set app [app::launchFore [getFileSig $name]]
  171.     sendOpenEvent -r [file tail $app] $name
  172. }
  173.  
  174. # Send multiple open events
  175. proc sendOpenEvents {appname args} {
  176.     AEBuild -r $appname aevt odoc "----" [makeAlises $args]
  177. }
  178.  
  179. proc openAndSendFile {sig} {
  180.     set fname [win::Current]
  181.     if {[winDirty]} {
  182.     if {[dialog::yesno "Save '$fname'?"]} {
  183.         save
  184.     }
  185.     }
  186.     
  187.     set name [file tail [app::launchFore $sig]]
  188.     sendOpenEvent noReply $name $fname
  189. }
  190.  
  191. #================================================================================
  192. # General Apple Event handling routines
  193. #
  194. # (written by Tom Pollard for use in the MacPerl package)
  195. #================================================================================
  196.  
  197. # Quit an application.
  198. proc sendQuitEvent {appname} {
  199.     AEBuild $appname "aevt" "quit" 
  200. }
  201.  
  202. # Close one of an application's windows, designated by number.
  203. proc sendCloseWinNum {appname num} {
  204.     AEBuild $appname "core" "clos" "----" [AEWinByPos $num]
  205. }
  206.  
  207. # Close one of an application's windows, designated by name.
  208. proc sendCloseWinName {appname name} {
  209.     AEBuild $appname "core" "clos" "----" [AEWinByName $name]
  210. }
  211.  
  212. # Obtain the number of lines in one of an application's
  213. # windows, designated by name.
  214. proc sendCountLines {appname name} {
  215.     set winObj [AEWinByName $name]
  216.     set res [AEBuild -r $appname "core" "cnte" "----" $winObj kocl type('clin')]    
  217.     if {[regexp {:(.*)\}} $res allofit nlines]} {
  218.     return $nlines
  219.     } else {
  220.     return 0
  221.     }
  222. }
  223.  
  224. # Get a selected range of lines from one of an application's
  225. # windows, designated by name.  If $last is missing, then a single
  226. # line is returned; if both $first and $last are missing, then
  227. # the complete window contents are returned.
  228. proc sendGetText {appname name {first {missing}} {last {missing}}} {
  229.     global ALPHA
  230.     set winObj [AEWinByName $name]
  231.     if {$first != "missing"} {
  232.     if {$last != "missing"} {
  233.         set rangDesc [AELineRange $first $last]
  234.     } else {
  235.         set rangDesc [AEAbsPos $first]
  236.     }
  237.     set objDesc "obj{want:type('clin'), from:$winObj, $rangDesc }"
  238.     } else {
  239.     set objDesc "obj{want:type('ctxt'), from:$winObj, form:'indx', seld:abso('all') }"
  240.     }
  241.     set res [AEBuild -r $appname "core" "getd" "----" $objDesc]
  242.     if {![regexp {“.*”} $res text]} { set text {} }
  243.     return [string trim $text {“”}]
  244. }
  245.  
  246. # Set a selected range of lines in one of an application's
  247. # windows, designated by name.  If $last is missing, then a single
  248. # line is changed; if both $first and $last are missing, then
  249. # the complete window contents are replaced by the new text.
  250. proc sendSetText {appname name text {first {missing}} {last {missing}}} {
  251.     set winObj [AEWinByName $name]
  252.     if {$first != "missing"} {
  253.     if {$last != "missing"} {
  254.         set rangDesc [AELineRange $first $last]
  255.     } else {
  256.         set rangDesc [AEAbsPos $first]
  257.     }
  258.     set objDesc "obj{want:type('clin'), from:$winObj, $rangDesc }"
  259.     } else {
  260.     set objDesc "obj{want:type('ctxt'), from:$winObj, form:'indx', seld:abso('all') }"
  261.     }
  262.     set res [AEBuild -r $appname "core" "setd" "----" $objDesc "data" [curlyq $text]]    
  263.     if {![regexp {“.*”} $res text]} { set text {} }
  264.     return [string trim $text {“”}]
  265. }
  266.  
  267. ################################################################################
  268. # Utility functions for constructing AppleEvent descriptors for AEBuild
  269. ################################################################################
  270.  
  271. # JEG - modernized
  272. #
  273. proc AEFilename {name} {
  274.     return [tclAE::build::filename $name]
  275. }
  276.  
  277. # JEG - modernized
  278. #
  279. proc AEWinByName {name} {
  280.     return [tclAE::build::winByName $name]
  281. }
  282.  
  283. # JEG - modernized
  284. #
  285. proc AEWinByPos {absPos} {
  286.     return [tclAE::build::winByPos $absPos]
  287. }
  288.  
  289. # JEG - modernized
  290. #
  291. proc AELineRange {absPos1 absPos2} {
  292.     return [tclAE::build::lineRange $absPos1 $absPos2]
  293. }
  294.  
  295. # JEG - modernized
  296. #
  297. proc AEAbsPos {posName} {
  298.     return [tclAE::build::absPos $posName]
  299. }
  300.  
  301. # JEG - modernized
  302. #
  303. proc AEName {name} {
  304.     return [tclAE::build::name $name]
  305. }
  306.  
  307. # JEG - modernized
  308. #
  309. proc curlyq {str} {
  310.     return [tclAE::build::TEXT $str]
  311. }
  312.  
  313. ################################################################################
  314.  
  315. # JEG - modernized
  316. #
  317. proc nullObject {} { 
  318.     return [tclAE::build::nullObject] 
  319. }
  320.  
  321. # JEG - modernized
  322. #
  323. proc objectType {type} {
  324.     return [tclAE::build::objectType $type]
  325. }
  326.  
  327. # JEG - modernized
  328. #
  329. proc nameObject {type name from} {
  330.     return [tclAE::build::nameObject $type $name $from]
  331. }
  332.  
  333. # JEG - modernized
  334. #
  335. proc indexObject {type ind from} {
  336.     return [tclAE::build::indexObject $type $ind $from]
  337. }
  338.  
  339. # JEG - modernized
  340. #
  341. proc propertyObject {prop object} { 
  342.     return [tclAE::build::propertyObject $prop $object]
  343. }
  344.  
  345.  
  346. # JEG - unused?
  347. # 'process' must have single quotes
  348. proc buildMsgReply { process suite event args } { return [eval [list AEBuild -r $process $suite $event ] $args] }
  349.  
  350. # JEG - modernized
  351. #
  352. proc countObjects { process fromObject class } {
  353.     return [tclAE::build::resultData $process core cnte \
  354.       ---- $fromObject \
  355.       kocl [tclAE::build::objectType $class] \
  356.     ]
  357. }
  358.  
  359. proc createThingAtEnd {process container class} {
  360.     set res [AEBuild -r $process core crel insh "insl \{kobj:$container\}" kocl "type($class)"]
  361. }
  362.  
  363.  
  364. proc getObjectData { process class name from } {
  365.     set res [AEBuild -r $process core getd ---- [nameObject $class "“$name”" $from] {rtyp{type:TEXT}}]
  366.     if {[regexp {“(.*)”} $res dummy mtch]} {
  367.     return $mtch
  368.     } else {
  369.     error "Bad count proc"
  370.     }
  371. }
  372.  
  373.  
  374. proc objectProperty { process property object } {
  375.     AEBuild -r $process core getd ---- [propertyObject $property $object]
  376. }
  377.  
  378. # Extract and return a path from a result.
  379. proc extractPath {res} {
  380.     if {[regexp {«(.*)»} $res dummy fss]} {
  381.     return [specToPathName $fss]
  382.     }
  383.     error "bad path $name"
  384. }    
  385.